package com.usian.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.usian.config.RedisClient;
import com.usian.mapper.*;
import com.usian.pojo.*;
import com.usian.service.ItemService;
import com.usian.utils.IDUtils;
import com.usian.utils.PageResult;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class ItemServiceImpl implements ItemService {

    @Autowired
    private TbItemMapper tbItemMapper;

    @Autowired
    private TbItemDescMapper tbItemDescMapper;

    @Autowired
    private TbItemParamItemMapper tbItemParamItemMapper;

    @Autowired
    private TbItemCatMapper tbItemCatMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private TbOrderItemMapper tbOrderItemMapper;

    @Value("${ITEM_INFO}")
    private String ITEM_INFO;

    @Value("${BASE}")
    private String BASE;

    @Value("${SETNX_BASC_LOCK_KEY}")
    private String SETNX_BASC_LOCK_KEY;

    //@Value("${DESC}")
    //private String DESC;

    //@Value("${PARAM}")
    //private String PARAM;

    @Value("${ITEM_INFO_EXPIRE}")
    private Integer ITEM_INFO_EXPIRE;

    @Override
    public TbItem selectItemInfo(Long itemId) {

        TbItem itemRedis = (TbItem) redisClient.get(ITEM_INFO+":"+BASE+":"+itemId);
        if(itemRedis !=null){
            return itemRedis;
        }
        TbItem item =new TbItem();
        //解决redis缓存击穿   使用redis 分布式锁  setnx
        if(redisClient.setnx(SETNX_BASC_LOCK_KEY+":"+itemId,itemId,30L) == true){
            //解决redis缓存穿透
            item = tbItemMapper.selectByPrimaryKey(itemId);
            if(item ==null){
                redisClient.set(ITEM_INFO+":"+BASE+":"+itemId,new TbItem(1L,"暂无数据"));
            }else{
                redisClient.set(ITEM_INFO+":"+BASE+":"+itemId,item);
            }
            redisClient.expire(ITEM_INFO+":"+BASE+":"+itemId,ITEM_INFO_EXPIRE);
            redisClient.del(SETNX_BASC_LOCK_KEY+":"+itemId);

        }else{
            try {
                Thread.sleep(2000L);
                return selectItemInfo(itemId);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return item;
    }

    @Override
    public PageResult selectTbItemAllByPage(Integer page, Integer rows) {
        //分页
        PageHelper.startPage(page,rows);

        //构建查询
        TbItemExample tbItemExample =new TbItemExample();
        TbItemExample.Criteria criteria = tbItemExample.createCriteria();
        criteria.andStatusEqualTo((byte)1);
        List<TbItem> list = tbItemMapper.selectByExample(tbItemExample);


        PageInfo<TbItem> pageInfo =new PageInfo<TbItem>(list);

        //封装结果
        PageResult pageResult = new PageResult();
        pageResult.setPageIndex(pageInfo.getPageNum());
        pageResult.setTotalPage(pageInfo.getPages());
        pageResult.setResult(pageInfo.getList());
        return pageResult;
    }

    @Override
    public Integer insertTbItem(TbItem item, String desc, String itemParams) {

        //1:item
        long id = IDUtils.genItemId();
        item.setId(id);
        item.setPrice(item.getPrice()*100);
        item.setCreated(new Date());
        item.setUpdated(new Date());
        item.setStatus((byte)1);
        int itemNum = tbItemMapper.insertSelective(item);

        //2:
        TbItemDesc itemDesc = new TbItemDesc();
        itemDesc.setItemId(item.getId());
        itemDesc.setItemDesc(desc);
        itemDesc.setCreated(new Date());
        itemDesc.setUpdated(new Date());
        int descNum = tbItemDescMapper.insertSelective(itemDesc);

        //3:
        TbItemParamItem paramItem = new TbItemParamItem();
        paramItem.setItemId(id);
        paramItem.setParamData(itemParams);
        paramItem.setCreated(new Date());
        paramItem.setUpdated(new Date());
        int paramNum = tbItemParamItemMapper.insertSelective(paramItem);


        //放商品id 消息值 放到消息队列
        amqpTemplate.convertAndSend("exchange_usian","item.insert",id);

        return itemNum+descNum+paramNum ; //3
    }

    @Override
    public Map<String, Object> preUpdateItem(Long itemId) {
        //item   itemdesc   itemcat   itemparam
        Map<String, Object> map = new HashMap<>();
        //根据商品 ID 查询商品
        TbItem item = this.tbItemMapper.selectByPrimaryKey(itemId);
        map.put("item", item);

        //根据商品 ID 查询商品描述
        TbItemDesc itemDesc = this.tbItemDescMapper.selectByPrimaryKey(itemId);
        if(itemDesc!=null){
            map.put("itemDesc", itemDesc.getItemDesc());
        }else{
            map.put("itemDesc", "");
        }

        //根据商品 ID 查询商品类目
        TbItemCat itemCat = this.tbItemCatMapper.selectByPrimaryKey(item.getCid());
        map.put("itemCat", itemCat.getName());


        //根据商品 ID 查询商品规格信息
        TbItemParamItemExample example = new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = example.createCriteria();
        criteria.andItemIdEqualTo(itemId);
        List<TbItemParamItem> list = tbItemParamItemMapper.selectByExampleWithBLOBs(example);

        if (list != null && list.size() > 0) {
            map.put("itemParamItem", list.get(0).getParamData());
        }
        return map;
    }

    @Override
    public Integer updateTbItem(TbItem item, String desc, String itemParams) {
        //1:item
        item.setPrice(item.getPrice()*100);
        item.setUpdated(new Date());
        item.setStatus((byte)1);
        int itemNum = tbItemMapper.updateByPrimaryKeySelective(item);

        //2:item_desc
        TbItemDesc itemDesc = new TbItemDesc();
        itemDesc.setItemId(item.getId());
        itemDesc.setItemDesc(desc);
        itemDesc.setUpdated(new Date());
        int descNum = tbItemDescMapper.updateByPrimaryKeySelective(itemDesc);

        //3:item_param_item
        TbItemParamItem paramItem = new TbItemParamItem();
        paramItem.setItemId(item.getId());
        paramItem.setParamData(itemParams);
        paramItem.setUpdated(new Date());
        TbItemParamItemExample example =new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = example.createCriteria();
        criteria.andItemIdEqualTo(item.getId());
        int paramNum = tbItemParamItemMapper.updateByExampleSelective(paramItem,example);


        //放商品id 消息值 放到消息队列
        amqpTemplate.convertAndSend("exchange_usian","item.update",item.getId());

        return itemNum+descNum+paramNum ;
    }

    @Override
    public Integer deleteItemById(Long itemId) {

        //1:item_param_item 物理删除
        TbItemParamItemExample example =new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = example.createCriteria();
        criteria.andItemIdEqualTo(itemId);
        int num = tbItemParamItemMapper.deleteByExample(example);

        //2:item_desc 物理删除
        int descNum = tbItemDescMapper.deleteByPrimaryKey(itemId);

        //3:item 逻辑删除
        TbItem item =new TbItem();
        item.setStatus((byte)3);
        item.setId(itemId);
        int itemNum = tbItemMapper.updateByPrimaryKeySelective(item);

        return num+descNum+itemNum;
    }

    /**
     * 扣减库存
     *
     * @param orderId
     * @return
     */
    @Override
    public Integer updateTbItemByOrderId(String orderId) {

        try {
            //1:order 查 orderItem  list
            TbOrderItemExample example =new TbOrderItemExample();
            TbOrderItemExample.Criteria criteria = example.createCriteria();
            criteria.andOrderIdEqualTo(orderId);
            List<TbOrderItem> itemList = tbOrderItemMapper.selectByExample(example);

            //list 遍历 itemId   tb_item   主键查   对象   num  update修改
            for(TbOrderItem orderItem :itemList){

                TbItem tbItem = tbItemMapper.selectByPrimaryKey(Long.valueOf(orderItem.getItemId()));
                if(tbItem.getNum()>0 && tbItem.getNum()>=orderItem.getNum()){
                    tbItem.setNum(tbItem.getNum() - orderItem.getNum());
                    tbItemMapper.updateByPrimaryKeySelective(tbItem);
                }
            }
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }
}
